package com.example.framework;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Random;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;


import com.example.data.ContactData;
import com.example.data.GroupData;

public class ContactHelper extends BaseHelperWithWebDriver{

	private Set<ContactData> contactsCache;

	public ContactHelper(ApplicationManager manager) {
		super(manager);
	}

	private void submitGroupDeletion() {
		click(By.name(manager.getProperties("delete")));
	}

	private void selectGroupByNumber(int numberOfGroup) {
		click(By.name(manager.getProperties("group")));
	}

	private void submitEdit() {
		click(By.name(manager.getProperties("update")));
	}

	private void submitDeletion() {
		click(By.xpath(manager.getProperties("submitDeletion")));

	}
	public Set<ContactData> getContactsList() {
		manager.getNavigationHelper().openSite();
		if (contactsCache == null) {
			buildCache();
		}
		return contactsCache;
	}
	private void buildCache() {
		contactsCache = new HashSet<ContactData>();
		manager.getNavigationHelper().openHomePage();// without this we are at EditAddBook entry
		List<WebElement> contactsCheckboxes = getCheckboxAtContactsPage();
		for (WebElement checkbox : contactsCheckboxes) {
			ContactData contact = getContactByNumberOfCheckbox(checkbox); 
			contactsCache.add(contact);
		}
	}

	public ArrayList<ContactData> getArrayContactsList() {
		manager.getNavigationHelper().openHomePage();
		ArrayList<ContactData> contactsList = new ArrayList<ContactData>();
		List<WebElement> contactsCheckboxes = getCheckboxAtContactsPage();
		for (WebElement checkbox : contactsCheckboxes) {
			ContactData contact = getContactByNumberOfCheckbox(checkbox); 
			contactsList.add(contact);
		}
		return contactsList;
	}

	public void createContact(ContactData contact, GroupData group) {
		manager.getNavigationHelper().openAddNewContactPage();
		boolean fillGroup = true;  //because group field is accessible when creating contact
		fillContactFields(contact, group, fillGroup);
		manager.getNavigationHelper().submitCreation();
		buildCache();
	}

	protected void fillContactFields(ContactData object, GroupData group, boolean fillGroup) {
		type(By.name(manager.getProperties("firstname")), object.firstName);
		type(By.name(manager.getProperties("lastname")), object.lastName);
		type(By.name(manager.getProperties("address")), object.address);
		type(By.name(manager.getProperties("home")), object.homeTel);
		type(By.name(manager.getProperties("mobile")), object.mobileTel);
		type(By.name(manager.getProperties("work")), object.workTel);
		type(By.name(manager.getProperties("email1")), object.email1);
		type(By.name(manager.getProperties("email2")), object.email2);
		select(By.name(manager.getProperties("birth_day")), object.day);
		select(By.name(manager.getProperties("birth_month")), object.month);		
		type(By.name(manager.getProperties("birh_year")), object.year);
		if (fillGroup) {
			select(By.name(manager.getProperties("new_group")), group.name);
		} 
		type(By.name(manager.getProperties("address2")), object.address2);
		type(By.name(manager.getProperties("phone2")), object.home2);
		
	}

	public ContactData modifyContactAndGetContactToModify(int numberOfContact, ContactData contact) {
		ContactData contactToModify = getContactByNumberOfCheckbox(numberOfContact);
		openContactByNumber(numberOfContact);
		boolean fillGroup = false;		
		GroupData group = new GroupData();
		fillContactFields(contact, group , fillGroup);
		submitEdit();
		returnToHomePageFromEditAddContactPage();
		buildCache();
		return contactToModify;
	}

	//sets groups for contact as a field. Not via UI
	public GroupData setRandomGroupInContact(ContactData contact) {
		Set<GroupData> groupsList = manager.getGroupHelper().getGroupsList();
		GroupData groupToSelect = new GroupData();
		int groupsSetSize = groupsList.size();
		if (groupsSetSize != 0) {
			Random rnd = new Random();
			groupToSelect = new ArrayList<GroupData>(groupsList).get(rnd.nextInt(groupsSetSize));
			contact.setGroup(groupToSelect);
		}
		return groupToSelect;
	}

	public ContactData deleteContactByNumber(int numberOfContact) {	
		manager.getNavigationHelper().openHomePage();
		ContactData contactToDelete =  getContactByNumberOfCheckbox(numberOfContact);
		openContactByNumber(numberOfContact);
		submitDeletion();
		returnToHomePageFromEditAddContactPage();
		buildCache();
		return contactToDelete;
	}

	private ContactData getContactByNumberOfCheckbox(int numberOfContact) {
		WebElement contactCheckboxByNumber = getCheckboxAtContactsPage().get(numberOfContact);
		return getContactByNumberOfCheckbox(contactCheckboxByNumber);
	}

	private ContactData openContactByNumber(int numberOfContact) {
		manager.getNavigationHelper().openHomePage();		
		selectContactByNumber(numberOfContact);
		return null;
	}

	private void selectContactByNumber(int numberOfContact) {
		findElement(By.xpath("//tbody/tr[" + (numberOfContact + 2) + "]/td[7]//img[@title='Edit']")).click();
	}

	public String[] getContactEmails(WebElement checkbox) {
		String[] contactEmails ={"", ""};
		Pattern p = Pattern.compile("(.*);(.*)|(.*)");	
		Matcher m = p.matcher(checkbox.getAttribute("accept"));
		m.matches();
		if (m.group(1)!=null) {
			contactEmails[0] = m.group(1);
			contactEmails[1] = m.group(2);
		} else {
			contactEmails[0] = m.group(3);
			contactEmails[1] = "";
		}
		return contactEmails;
	}

	private ContactData getContactByNumberOfCheckbox(WebElement checkbox) {
		String[] contactEmails;
		String contactFirstName;
		String contactLastName;
		String contactID = checkbox.getAttribute("id");

		contactEmails =getContactEmails(checkbox);

		Pattern p = Pattern.compile("Select \\((.* .*) (.* .*)\\)|Select \\((.*) (.*)\\)");	
		Matcher m = p.matcher(checkbox.getAttribute("alt"));
		m.matches();
		if (m.group(1)!=null) {
			contactFirstName = m.group(1);
			contactLastName = m.group(2);
		} else {
			contactFirstName = m.group(3);
			contactLastName = m.group(4);
		}
		return new ContactData().setId(contactID).setFirstName(contactFirstName)
				.setLastName(contactLastName).setEmail1(contactEmails[0]).setEmail2(contactEmails[1]);
	}

	private List<WebElement> getCheckboxAtContactsPage() {
		return findElements(By.xpath(manager.getProperties("contactCheckbox")));
	}
	public void returnToHomePageFromEditAddContactPage() {
		click(By.linkText(manager.getProperties("homePage")));
	}

	public int getNumberOfContactsAtPrintPhonesPage() {
		manager.getNavigationHelper().goToPrintPhonesPage();
		int numOfRows = findElements(By.xpath("//table/tbody/tr")).size();
		int numOfContactsInLastRow = findElements(By.xpath("//table/tbody/tr[" + numOfRows + "]/td[@valign='top']")).size();
		int totalNumberOfContacts;
		if (numOfRows > 0) {
			totalNumberOfContacts = (numOfRows - 1)*3 + numOfContactsInLastRow;
		} else {
			totalNumberOfContacts = 0;
		}
		return totalNumberOfContacts;
	}

	public ContactData getContactAtPrintPhonesPageByNumber(int numberOfContact) {
		manager.getNavigationHelper().goToPrintPhonesPage();
		String numOfRow = Integer.toString(numberOfContact/3 + 1);
		String numOfColumn = Integer.toString(numberOfContact % 3);
		String contactName = getText(By.xpath(contactInfoCellXPath(numOfRow, numOfColumn) + "/br"));
		String contactHomeTel = getText(By.xpath(contactInfoCellXPath(numOfRow, numOfColumn))).replaceAll("H: (.*)", "$1");

		return new ContactData().setFirstName(contactName.replaceAll("(.* .*) (.* .*)", "$1")).setLastName(contactName.replaceAll("(.* .*) (.* .*)", "$2")).setHomeTel(contactHomeTel);
	}

	private String contactInfoCellXPath(String tr, String td) {
		return "//table/tbody/tr[" + tr + "]/td[@valign='top'][" + td + "]";
	}

	public ArrayList<ContactData> getListOfContactsAtPrintPhonesPage() {
		manager.getNavigationHelper().goToPrintPhonesPage();
		int numberOfContact = getNumberOfContactsAtPrintPhonesPage();
		ArrayList<ContactData> list = new ArrayList<ContactData>();
		for (int i = 1; i < numberOfContact + 1; i++) {
			String numOfRow = Integer.toString(((i % 3)==0)? i/3 :(i/3 + 1));
			String numOfColumn = Integer.toString(((i % 3)==0)? 3 :(i % 3));
			System.out.println("numOfRow = " + numOfRow + " numOfColumn = " + numOfColumn);
			String contactName = getText(By.xpath(contactInfoCellXPath(numOfRow, numOfColumn) + "/b"));
			String contactHomeTel = getText(By.xpath(contactInfoCellXPath(numOfRow, numOfColumn))).replaceAll(".*:\\s*H: (.*)\\s*M:.*[\\s\\S]*", "$1");
			ContactData contact = new ContactData().setFirstName(contactName.replaceAll("(\\S*\\s*\\S*) \\S*\\s*\\S*", "$1")).setLastName(contactName.replaceAll("\\S*\\s*\\S* (\\S*\\s*\\S*)", "$1")).setHomeTel(contactHomeTel);
			list.add(contact);
		}
		return list;
	}
}
